using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEditor;
using UnityEditor.IMGUI.Controls;
using UnityEditorInternal;
using UnityEngine;
using Object = UnityEngine.Object;

namespace FAssetsSeparate
{
    public class PrefabTreeView : TreeView
    {
        /// <summary> 路径列表 </summary>
        public List<string> paths => _itemPath;

        /// <summary> 树图元素 </summary>
        readonly List<TreeViewItem> _viewItems = new();

        /// <summary> 记录树图加载路径 方便做同路径排除 </summary>
        readonly List<string> _itemPath = new();

        /// <summary> label 显示样式 </summary>
        GUIStyle _labelStyle;

        public PrefabTreeView(TreeViewState state) : base(state) => Reload();

        protected override TreeViewItem BuildRoot()
        {
            var root = new TreeViewItem { id = 0, depth = -1, displayName = "Root" };

            // 根据节点在树结构中的深度，在节点之间建立父子关系。
            SetupParentsAndChildrenFromDepths(root, _viewItems);
            return root;
        }

        protected override void RowGUI(RowGUIArgs args)
        {
            var rect = args.rowRect;

            if (_labelStyle == null)
            {
                _labelStyle = new GUIStyle("label");
                _labelStyle.richText = true;
            }

            var dirName = Path.GetDirectoryName(args.label)?.Replace("\\", "/");
            var fileName = Path.GetFileName(args.label);
            var icon = GetIcon(args.label);
            GUI.Label(new Rect(rect.x, rect.y, rect.width, rect.height), icon);
            GUI.Label(new Rect(rect.x + 20, rect.y, rect.width, rect.height), $"<color=grey>{dirName}/</color>{fileName}", _labelStyle);

            var evt = Event.current;

            // 双击定位
            if (evt.type == EventType.MouseDown && evt.clickCount == 2)
            {
                if (GetSelection().Contains(args.item.id) && args.rowRect.Contains(evt.mousePosition))
                {
                    PingAsset();
                    evt.Use();
                }
            }

            // 按键删除
            if (evt.type == EventType.KeyDown && evt.keyCode == KeyCode.Delete)
            {
                if (!GetSelection().Contains(args.item.id))
                    return;
                DeleteSelect();
                evt.Use();
            }
        }

        /// <summary> 添加路径 </summary>
        /// <param name="path">路径</param>
        public void AddPath(string path)
        {
            if (_itemPath.Contains(path))
                return;

            _itemPath.Add(path);
            _viewItems.Add(new TreeViewItem(_viewItems.Count, 0, path));
        }

        /// <summary> 清除 </summary>
        public void Clear()
        {
            _viewItems.Clear();
            _itemPath.Clear();
            Reload();
        }

        /// <summary> 删除选择 </summary>
        void DeleteSelect()
        {
            var tvItems = new List<TreeViewItem>(GetRows());
            var removesIndex = GetSelection().ToArray();

            // 对索引数组进行降序排序，确保移除操作不会影响后续索引
            Array.Sort(removesIndex);
            Array.Reverse(removesIndex);

            // 移除指定索引处的元素
            foreach (var index in removesIndex)
            {
                if (index >= 0 && index < tvItems.Count)
                {
                    tvItems.RemoveAt(index);
                    _itemPath.RemoveAt(index);
                }
            }

            // 清理 TreeViewItem 刷新填充
            _viewItems.Clear();
            for (var i = 0; i < tvItems.Count; i++)
                _viewItems.Add(new TreeViewItem(i, 0, tvItems[i].displayName));

            Reload();
            SetSelection(Array.Empty<int>());
        }

        /// <summary> Ping 资产 </summary>
        void PingAsset()
        {
            var obj = AssetDatabase.LoadAssetAtPath<Object>(GetRows()[GetSelection()[0]].displayName);
            EditorGUIUtility.PingObject(obj);
            Selection.activeObject = obj;
        }

        /// <summary> 获取 icon </summary>
        static Texture GetIcon(string path)
        {
            // 资产路径
            var icon = AssetDatabase.GetCachedIcon(path);
            if (!icon)
                icon = InternalEditorUtility.GetIconForFile(path);

            return icon;
        }
    }
}